This page last changed on Oct 20, 2006 by cholmes.
Extending GeoServer's configuration IO has four steps:
- Create a Bean or Attribute to store your new information
- Load your information from XML
- Use you information to set up GeoServer
- Write your information to XML
Although in practice many of these processes are completed concurently and closely depend upon each other, we are going to pretend we live in a perfect linear world.
Data Transfer Objects
The DTO objects closely resemble the structure of the XML files. The DTO objects should contain data in a logical grouping, independant of the application and user interface. So if it belongs with other like data, put it there. For example above we would store serviceLevel as an enumerated type in the WFSDTO object. But if we also wanted to store serviceLevels for the WMS service this information would be stored in the ServiceDTO Object, with the enumeration of types residing in the WFSDTO and WMSDTO Objects respectively.
Data Transfer Object Extension
Make sure all of the following tasks have been completed (example from WFSDTO.java):
Update default construtor
public WFSDTO(){
serviceLevel = WFSDTO.BASIC; }
Update parametarized constructor used to clone
public WFSDTO(WFSDTO other) {
if (other == null) {
throw new NullPointerException("Data Transfer Object required");
}
service = (ServiceDTO) new ServiceDTO(other.getService());
gmlPrefixing = other.isGmlPrefixing();
serviceLevel = WFSDTO.getServiceLevel(); }
Update equals method
public boolean equals(Object other) {
if ((other == null) || !(other instanceof WFSDTO)) {
return false;
}
WFSDTO dto = (WFSDTO) other;
return (serviceLevel == dto.getServiceLevel() && service == null) ? (dto.getService() == null)
: service.equals(dto.getService()));
}
Generate getter and setter methods
public int getServiceLevel(){
return serviceLevel;
}
public void setServiceLevel(int serviceLevel){
this.serviceLevel = serviceLevel;
}
Document the changes in the source code
/** ServiceLevel bit used to indicate Basic support */
public static final int SERVICE_BASIC = 1;
/** ServiceLevel bit used to indicate Transaction Insert support */
public static final int SERVICE_INSERT = 2;
/** ServiceLevel bit used to indicate Transaction Update support */
public static final int SERVICE_UPDATE = 4;
/** ServiceLevel bit used to indicate Transaction Delete support */
public static final int SERVICE_DELETE = 8;
/** ServiceLevel bit used to indicate Locking support */
public static final int SERVICE_LOCKING = 16;
/** ServiceLevel mask equivilent to basic WFS conformance */
public static final int BASIC = 1;
/** ServiceLevel mask for transactional WFS conformance. */
public static final int TRANSACTIONAL = SERVICE_BASIC | SERVICE_INSERT
| SERVICE_UPDATE | SERVICE_DELETE;
/** ServiceLevel mask equivilent to complete WFS conformance */
public static final int COMPLETE = TRANSACTIONAL | SERVICE_LOCKING;
XMLConfigReader
Extending the XML Reader is relatively easy to complete, but equally easy to break the application. As a general warning if you are not happy playing with DOM trees you should brush up on your XML skills before entering this stage of developement.
The file XMLConfigReader may extended at several locations:
- XMLConfigReader( File rootDir ) - calls load method on creation
- load() - extend to add support for additional configuration files
- loadService(Element) - extend for parsing common to both WMS and WFS
- loadWMS(Element) - extend for parsing Web Map Server
- loadWFS(Element) - extend for parsing Web Feature Server
- loadGlobal(Elemenet) - extend for parsing GeoServerDTO
- load
For the DOM efficiados out there all you need to do is add the code to read the Element at the correct point in the file which you intend to read from. Often this is easier said than done, but once completed place the data into the DTO object.
The best advice I have for you is to be VERY careful of your element pointer withing the DOM tree. If you inadvertantly affect this pointer, all other parsing one the remaining interior branches of that tree will not be parsed correctly, mostlikely breaking atleast part of the application.
How to be VERY careful? Try one of the following:
- make a private method an pass the ref in - for an example check out
- make a copy of the reference before playing with it
Just like the previous step, I have included a short list to help ensure you have completed everything (example XMLConfigReader.java).
Ensure you have not affected the Element references around you new addition (XMLConfigReader.processSchema() )
elem = ReaderUtils.getChildElement(elem, "xs:sequence");
NodeList nl = elem.getElementsByTagName("xs:element");
for (int i = 0; i < nl.getLength(); i++) {
Element element = (Element) nl.item(i);
Test the application to ensure it is not broken (ie. run cite tests)
Document the changes in the source code
elem = ReaderUtils.getChildElement(elem, "xs:sequence");
NodeList nl = elem.getElementsByTagName("xs:element");
for (int i = 0; i < nl.getLength(); i++) {
Element element = (Element) nl.item(i);
Ensure you have included informative error messages where appropriate.
catch(ConfigurationException e){
throw new ConfigurationException("io error");
}
catch(ConfigurationException e){
throw new ConfigurationException("Error occured in "+schemaFile+"\n"+e.getMessage(),e);
}
Optimization
You may optimize this process for speed (rather than saftey):
elem = ReaderUtils.getChildElement(elem, "xs:sequence");
NodeList nl = elem.getElementsByTagName("xs:element");
for (int i = 0; i < nl.getLength(); i++) {
elem = (Element) nl.item(i);
And once again be VERY careful, if you loose the readers place in the DOM tree. The errors will not be thrown from your code, but from else where in the reading process.
XMLConfigWriter
This portion is the reverse of the XML Reader. You need to add the write methods for your new data. Try to use the element write methods provided. Also you should be careful to match tags ... . Remember to test this code as well, because this code will break the application as badly as the reader next time you run it.
- Test the application to ensure it is not broken (ie. run cite tests)
- Document the changes in the source code
if ((wfs.getTitle() != null) && (wfs.getTitle() != WFSDTO.BASIC)) {
cw.textTag("serviceLevel", wfs.getServiceLevel()+"");
}
- Ensure you have included informative error messages where appropriate.
catch(ConfigurationException e){
throw new ConfigurationException("io error");
}
catch(ConfigurationException e){
throw new ConfigurationException("Error occured in WFS service configuration output.\n"+e.getMessage(),e);
}
|